package com.example.controller;

import com.example.entity.RestBean;
import com.example.entity.dto.Account;
import com.example.entity.dto.AccountDetails;
import com.example.entity.vo.request.ChangPasswordVO;
import com.example.entity.vo.request.DetailsSaveVO;
import com.example.entity.vo.request.ModifyEmailVO;
import com.example.entity.vo.request.PrivacySaveVO;
import com.example.entity.vo.response.AccountDetailsVO;
import com.example.entity.vo.response.AccountPrivacyVO;
import com.example.entity.vo.response.AccountVO;
import com.example.service.AccountDetailsService;
import com.example.service.AccountPrivacyService;
import com.example.service.AccountService;
import com.example.utils.Const;
import com.example.utils.ControllerUtils;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Optional;
import java.util.function.Supplier;

/**
 * 作者:xuSen
 * 日期2025/4/22 15:10
 */
@RestController
@Slf4j
@RequestMapping("/api/user")
public class AccountController {
    @Resource
    private AccountService accountService;
    @Resource
    private AccountDetailsService accountDetailsService;
    @Resource
private AccountPrivacyService accountPrivacyService;
    @Resource
    private ControllerUtils utils;
    /**
     * 获取用户账户信息
     * 此方法通过GET请求获取当前用户ID关联的账户信息，并以AccountVO对象的形式返回
     * 使用RequestAttribute注解从请求中提取用户ID，避免了直接在请求参数中暴露用户敏感信息
     *
     * @param id 用户ID，通过RequestAttribute注解获取
     * @return 包含账户信息的RestBean对象
     */
    @GetMapping("/info")
    public RestBean<AccountVO> info(@RequestAttribute(Const.ATTR_USER_ID) int id) {
        // 根据用户ID查询账户信息
        Account account = accountService.findAccountById(id);
        // 将账户信息转换为AccountVO对象，并封装到RestBean中返回
        return RestBean.success(account.asViewObject(AccountVO.class));
    }

    /**
     * 获取用户账户详细信息
     *
     * 此方法通过用户ID查询账户详细信息，如果找不到相关信息，则返回一个空的账户详情对象
     * 使用RequestAttribute注解从请求中提取用户ID，这通常在前面的处理中已经验证和解析
     *
     * @param id 用户ID，用于查询账户详情
     * @return 返回包含账户详细信息的RestBean对象，如果找不到信息，则返回空账户详情对象
     */
    @GetMapping("/details")
    public RestBean<AccountDetailsVO> details(@RequestAttribute(Const.ATTR_USER_ID) int id) {
        // 使用Optional处理可能的空值情况，提高代码的健壮性
        AccountDetails accountDetails = Optional
                .ofNullable(accountDetailsService.findAccountDetailsById(id))
                .orElseGet(AccountDetails::new);
        // 将AccountDetails对象转换为视图对象(AccountDetailsVO)并封装到RestBean中返回
        return RestBean.success(accountDetails.asViewObject(AccountDetailsVO.class));
    }

    /**
     * 保存用户详情信息
     * 此方法通过Post请求接收用户详情数据，并尝试保存到数据库中
     * 如果用户名已被其他用户使用，则返回失败信息
     *
     * @param id 用户ID，通过请求属性获取
     * @param vo 用户详情信息，以请求体形式传入，并进行数据有效性校验
     * @return RestBean<Void> 返回一个空泛型的RestBean对象，表示操作成功或失败
     */
    @PostMapping("/save-details")
    public RestBean<Void> saveDetails(@RequestAttribute(Const.ATTR_USER_ID) int id,
                                      @RequestBody @Valid DetailsSaveVO vo) {
        // 尝试保存用户详情信息，根据返回结果构建相应的响应
        boolean success = accountDetailsService.saveAccountDetails(id, vo);
        // 根据保存结果返回相应的HTTP状态码和消息
        return success ? RestBean.success() : RestBean.failure(400, "此用户名已经被其他用户使用，请重新更换");
    }
    /**
     * 修改用户邮箱
     * 此方法通过POST请求处理用户修改邮箱的请求
     * 它首先从请求属性中提取用户ID，然后获取经过验证的修改邮箱的视图对象
     * 最后，调用账户服务的modifyEmail方法来更新用户的邮箱信息
     *
     * @param id 用户ID，从请求属性中获取
     * @param vo 包含新邮箱信息的视图对象，经过验证
     * @return RestBean<Void> 返回一个表示操作结果的RestBean对象
     */
    @PostMapping("/modify-email")
    public RestBean<Void> modifyEmail(@RequestAttribute(Const.ATTR_USER_ID) int id,
                                      @RequestBody @Valid ModifyEmailVO vo) {
//         调用账户服务的modifyEmail方法，尝试更新用户的邮箱信息
        String s = accountService.modifyEmail(id, vo);
//         根据更新结果，返回相应的响应对象
//         如果更新成功，返回成功响应；如果更新失败，返回包含错误信息的失败响应
        return s==null?RestBean.success():RestBean.failure(400,s);
        // 以下代码存在逻辑错误，不应在此处出现，因为modifyEmail方法的返回类型不匹配
        // 此外，这段代码永远不会被执行，因为它位于方法的末尾，且前面已有return语句
//        return messageHandle(() -> accountService.modifyEmail(id, vo));
    }

    /**
     * 处理更改密码请求
     * 此方法接收用户ID和新密码信息，调用服务层方法为用户更改密码
     *
     * @param id 用户ID，用于标识需要更改密码的用户
     * @param vo 包含新密码信息的ChangPasswordVO对象，用于接收客户端提交的新密码数据
     * @return RestBean<Void> 返回一个表示操作结果的RestBean对象，包含操作成功或失败的信息
     */
    @PostMapping("/change-password")
    public RestBean<Void> changePassword(@RequestAttribute(Const.ATTR_USER_ID) int id,
                                         @RequestBody @Valid ChangPasswordVO vo) {
        // 调用服务层方法更改用户密码，并接收更改结果
//        String s = accountService.changePassword(id,vo);
        // 根据更改结果返回成功或失败的响应
//        return s==null?RestBean.success():RestBean.failure(400,s);
        // 简化代码
        return utils.messageHandle(() -> accountService.changePassword(id, vo));
    }

    /**
     * 保存用户隐私设置的接口
     * 此方法接收用户ID和隐私设置信息，将用户的隐私设置保存到系统中
     *
     * @param id 用户ID，用于标识和定位用户
     * @param vo PrivacySaveVO类型的对象，包含用户想要保存的隐私设置信息
     *           该对象通过@Valid注解进行参数校验，确保数据的合法性
     * @return RestBean<Void>类型，表示隐私设置保存操作的结果
     *         成功保存隐私设置后，返回成功状态的RestBean对象
     */
    @PostMapping("/save-privacy")
    public RestBean<Void> savePrivacy(@RequestAttribute(Const.ATTR_USER_ID) int id,
                                      @RequestBody @Valid PrivacySaveVO vo) {
        // 简化代码，调用服务层方法保存隐私设置
        accountPrivacyService.savePrivacy(id, vo);
        // 返回成功状态的响应
        return RestBean.success();
    }

    /**
     * 获取用户隐私设置的接口
     * 此方法根据用户ID获取并返回用户的隐私设置信息
     *
     * @param id 用户ID，用于获取特定用户的隐私设置
     * @return RestBean<AccountPrivacyVO>类型，包含用户隐私设置的响应对象
     *         成功获取隐私设置后，返回包含隐私设置信息的RestBean对象
     */
    @GetMapping("/privacy")
    public RestBean<AccountPrivacyVO> Privacy(@RequestAttribute(Const.ATTR_USER_ID) int id) {
        // 调用服务层方法获取用户隐私设置，并转换为AccountPrivacyVO类型的视图对象返回
        return RestBean.success(accountPrivacyService.accountPrivacy(id).asViewObject(AccountPrivacyVO.class));
    }



}






















